#! /usr/bin/env python
# -*- coding: UTF-8 -*-

# This file is part of emule local client
# 
# The eMule Local Client is free software, you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# eMule Local Client is distributed in the hope that it will be useful
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with eMule Local Client; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import gtk

import Core
import HistoryWindow
from constant import *

class MainWindow(gtk.Window):

    def __init__(self):
        self.server_url = None
        self.session_id = None

        gtk.Window.__init__(self)
        self.set_resizable(True)
        self.set_border_width(0)
        self.resize(640, 480)

        self.connect("destroy", self.destroy)

        vbox = gtk.VBox(False, 0)
        self.add(vbox)

        menubar = gtk.MenuBar()
        vbox.pack_start(menubar, expand=False)

        menu = gtk.Menu()
        menuitem = gtk.MenuItem('_Server')
        agr = gtk.AccelGroup()
        self.add_accel_group(agr)

        self.connect_menuitem = gtk.ImageMenuItem(gtk.STOCK_CONNECT, agr)
        key, mod = gtk.accelerator_parse("O")
        self.connect_menuitem.add_accelerator('activate', agr, key, mod, gtk.ACCEL_VISIBLE)
        self.connect_menuitem.connect("activate", self.on_connect_to_server)

        self.disconnect_menuitem = gtk.ImageMenuItem(gtk.STOCK_DISCONNECT, agr)
        key, mod = gtk.accelerator_parse("D")
        self.disconnect_menuitem.add_accelerator('activate', agr, key, mod, gtk.ACCEL_VISIBLE)
        self.disconnect_menuitem.connect("activate", self.on_disconnect_from_server)

        self.exit_menuitem = gtk.ImageMenuItem(gtk.STOCK_QUIT, agr)
        key, mod = gtk.accelerator_parse("Q")
        self.exit_menuitem.add_accelerator('activate', agr, key, mod, gtk.ACCEL_VISIBLE)
        self.exit_menuitem.connect('activate', self.destroy)
        menu.add(self.connect_menuitem)
        menu.add(self.disconnect_menuitem)
        menu.add(gtk.SeparatorMenuItem())
        menu.add(self.exit_menuitem)
        menuitem.set_submenu(menu)
        menubar.add(menuitem)

        menu = gtk.Menu()
        menuitem = gtk.MenuItem('_Edit')
        self.always_on_top_menuitem = gtk.CheckMenuItem('Always on _top')
        self.always_on_top_menuitem.connect('toggled', self.on_always_on_top)
        self.paste_menuitem = gtk.ImageMenuItem(gtk.STOCK_PASTE)
        self.paste_menuitem.connect('activate', self.on_paste)
        self.show_tray_menuitem = gtk.CheckMenuItem('S_how icon in system tray')
        self.show_tray_menuitem.connect('toggled', self.on_show_tray)
        menu.add(self.always_on_top_menuitem)
        menu.add(self.paste_menuitem)
        menu.add(gtk.SeparatorMenuItem())
        menu.add(self.show_tray_menuitem)
        menuitem.set_submenu(menu)
        menubar.add(menuitem)

        menu = gtk.Menu()
        menuitem = gtk.MenuItem('_Help')
        self.about_menuitem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
        self.about_menuitem.connect('activate', self.on_about)
        self.history_menuitem = gtk.MenuItem('History')
        self.history_menuitem.connect('activate', self.on_show_download_history)
        menu.add(self.history_menuitem)
        menu.add(gtk.SeparatorMenuItem())
        menu.add(self.about_menuitem)
        menuitem.set_submenu(menu)
        menubar.add(menuitem)

        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)

        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.textview = gtk.TextView()
        textbuffer = self.textview.get_buffer()
        self.textview.set_wrap_mode(gtk.WRAP_CHAR)
        self.textview.set_border_window_size(gtk.TEXT_WINDOW_LEFT, 20)
        self.textview.connect("expose_event", self.line_numbers_expose)
        sw.add(self.textview)
        vbox.pack_start(sw, True, True, 0)

        separator = gtk.HSeparator()
        vbox.pack_start(separator, False, True, 0)
        
        button_box = gtk.HBox(False, 0)
        self.download_button = gtk.Button("_Download", gtk.STOCK_EXECUTE)
        self.download_button.connect("clicked", self.on_download, textbuffer)
        button_box.pack_start(self.download_button, True, False, 0)
        vbox.pack_start(button_box, False, False, 0)

        self.statusbar = gtk.Statusbar()
        vbox.pack_start(self.statusbar, False, False, 0)
        self.show_all()
        
        self.statusicon = gtk.status_icon_new_from_stock(gtk.STOCK_SAVE_AS)
        self.statusicon.connect('popup-menu', self.on_statusicon_click)
        self.statusicon.set_visible(False)

        self.is_connected = False
        self.set_ui_sensitive(False)

    def set_ui_sensitive(self, sensitive):
        self.set_title('(%s Ver%s) %s connected' % (APP_NAME, APP_VER, sensitive and self.server_url or 'NOT'))
        self.download_button.set_sensitive(sensitive)
        self.textview.set_sensitive(sensitive)
        self.disconnect_menuitem.set_sensitive(sensitive)
        self.connect_menuitem.set_sensitive(not sensitive)
        self.paste_menuitem.set_sensitive(sensitive)
        self.statusbar.push(1, '%s connected' % (sensitive and self.server_url or 'NOT'))
        
    def on_statusicon_click(self, icon, event_button, event_time):
        menu = gtk.Menu()
        #item = gtk.CheckMenuItem('Monitor Clipboard')
        #menu.append(item)
        #menu.append(gtk.SeparatorMenuItem())
        item = gtk.ImageMenuItem(gtk.STOCK_QUIT)
        item.connect('activate', self.destroy)
        menu.append(item)
        menu.show_all()
        menu.popup(None, None, gtk.status_icon_position_menu, event_button, event_time, icon)
        
    def on_show_tray(self, widget):
        self.statusicon.set_visible(widget.active)    

    def destroy(self, widget):
        if self.is_connected:
            Core.logout(self.server_url, self.session_id)

        gtk.main_quit()

    def on_about(self, widget):
        gtk.about_dialog_set_url_hook(lambda dialog, link, data: webbrowser.open(link))
        about = gtk.AboutDialog()
        about.set_program_name(APP_NAME)
        about.set_version(APP_VER)
        about.set_copyright(APP_COPYRIGHT)
        about.set_comments(APP_COMMENTS)
        about.set_website(APP_WEBSITE)
        about.set_license(APP_LICENSE)
        about.set_translator_credits(APP_TRANSLATORS)
        about.run()
        about.destroy()

    def on_always_on_top(self, widget):
        self.set_keep_above(widget.active)

    def on_paste(self, widget):
        clipboard = gtk.Clipboard(gtk.gdk.display_manager_get().get_default_display(), 'CLIPBOARD')
        clipboard.request_text(self.clipboard_text_received)

    def clipboard_text_received(self, clipboard, targets, info):
        tb = self.textview.get_buffer()
        original_text = tb.get_text(tb.get_start_iter(), tb.get_end_iter(), False)
        tb.set_text(original_text + targets.rstrip().lstrip())

    def line_numbers_expose(self, widget, event, user_data=None):
        text_view = widget

        target = text_view.get_window(gtk.TEXT_WINDOW_LEFT)
        type = gtk.TEXT_WINDOW_LEFT

        first_y = event.area.y
        last_y = first_y + event.area.height

        x, first_y = text_view.window_to_buffer_coords(type, 0, first_y)
        x, last_y = text_view.window_to_buffer_coords(type, 0, last_y)

        numbers = []
        pixels = []

        count = self.get_lines(first_y, last_y, pixels, numbers)

        layout = widget.create_pango_layout("")

        for i in range(count):
            x, pos = text_view.buffer_to_window_coords(type, 0, pixels[i])
            layout.set_text("%d" % (numbers[i] + 1))
            widget.style.paint_layout(target, widget.state, False, None, widget, None, 2, pos + 2, layout)

        return False

    def get_lines(self, first_y, last_y, buffer_coords, numbers):
        text_view = self.textview

        iter, top = text_view.get_line_at_y(first_y)
        count, size = 0, 0

        while not iter.is_end():
            y, height = text_view.get_line_yrange(iter)
            buffer_coords.append(y)
            line_num = iter.get_line()
            numbers.append(line_num)
            count += 1
            if (y + height) >= last_y:
                break
            iter.forward_line()

        return count

    def on_download(self, widget, textbuffer):
        links_text = textbuffer.get_text(textbuffer.get_start_iter(), textbuffer.get_end_iter(), False)
        tasks = Core.batch_download(self.server_url, self.session_id, links_text)

        info_dialog = gtk.MessageDialog(self, 
                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 
                        gtk.MESSAGE_INFO, gtk.BUTTONS_OK, 
                        "%d task%s added\n\n%s" % (len(tasks), 's' if len(tasks) > 1 else '', '\n'.join(tasks)))

        info_dialog.run()
        info_dialog.destroy()
        textbuffer.set_text('')

    def on_show_download_history(self, widget):
        history_window = HistoryWindow.HistoryWindow(self, HISTORY_FILE, self.server_url, self.session_id)
        history_window.show()

    def on_disconnect_from_server(self, widget):
        Core.logout(self.server_url, self.session_id)
        self.is_connected = False
        self.set_ui_sensitive(False)

    def on_connect_to_server(self, widget):
        dialog = gtk.Dialog('Connect to server', self, 0, 
                        (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))

        hbox = gtk.HBox(False, 8)
        hbox.set_border_width(8)
        dialog.vbox.pack_start(hbox, False, False, 0)

        stock = gtk.image_new_from_stock(
                        gtk.STOCK_DIALOG_QUESTION,
                        gtk.ICON_SIZE_DIALOG)
        hbox.pack_start(stock, False, False, 0)

        table = gtk.Table(2, 2)
        table.set_row_spacings(4)
        table.set_col_spacings(4)
        hbox.pack_start(table, True, True, 0)

        label = gtk.Label("_Server")
        label.set_use_underline(True)
        table.attach(label, 0, 1, 0, 1)
        server_entry = gtk.Entry()
        table.attach(server_entry, 1, 2, 0, 1)

        server_completion = gtk.EntryCompletion()
        server_entry.set_completion(server_completion)
        server_completion.set_model(self.__create_server_completion_model())
        server_completion.set_text_column(0)

        label.set_mnemonic_widget(server_entry)

        label = gtk.Label("_Password")
        label.set_use_underline(True)
        table.attach(label, 0, 1, 1, 2)
        password_entry = gtk.Entry()
        password_entry.set_visibility(False)
        table.attach(password_entry, 1, 2, 1, 2)
        label.set_mnemonic_widget(password_entry)

        dialog.show_all()

        response = dialog.run()

        if response == gtk.RESPONSE_OK:
            # try to login
            self.server_url, password = server_entry.get_text(), password_entry.get_text()
            self.session_id = Core.get_session_id(Core.login(self.server_url, password))
        
            if self.session_id != None:   
                self.is_connected = True 
                self.set_ui_sensitive(True)
                info_dialog = gtk.MessageDialog(dialog, 
                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 
                        gtk.MESSAGE_INFO, gtk.BUTTONS_OK, 
                        "Login Successfully")
                info_dialog.run()
                info_dialog.destroy()
            else :
                warn_dialog = gtk.MessageDialog(dialog, 
                        gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, 
                        gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, 
                        "Login Failed")
                self.server_url = ''
                warn_dialog.run()
                warn_dialog.destroy()
        
        dialog.destroy()

    def __create_server_completion_model(self):
        store = gtk.ListStore(str)
        iter = store.append()
        store.set(iter, 0, "http://10.0.0.199:9999")
        
#        iter = store.append()
#        store.set(iter, 0, "http://10.0.1.199:9999")

        return store
        

def main():
    MainWindow()
    gtk.main()

    
if __name__ == "__main__":
    main()
